package com.webside.file.controller;

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSFile;
import com.webside.file.result.FileResult;
import com.webside.file.result.ResultEntity;
import com.webside.file.result.ResultEntity.ResultCode;
import com.webside.file.service.FileService;

@RestController
@RequestMapping("files")
public class FileController {
	private static final Logger log = Logger.getLogger(FileController.class);
	@Autowired
	FileService fileService;

	@RequestMapping(value = "/cutting/img", method = RequestMethod.POST)
	public ResultEntity<List<FileResult>> imgCutting(
			@RequestParam String imgid,
			@RequestParam int pointX,
			@RequestParam int pointY,
			@RequestParam int pointW,
			@RequestParam int pointH,
			@RequestParam int scaleW,
			@RequestParam int scaleH) {
		log.info("文件id：" + imgid);
		// 取出图片
		GridFSDBFile gfile = fileService.find(imgid);
		String filePrefix = gfile.getFilename().substring(gfile.getFilename().lastIndexOf(".") + 1);
		// 切割图片
		try {
			// 缩放图片
			BufferedImage bufferImage = ImageIO.read(gfile.getInputStream());
			bufferImage = resize(bufferImage, scaleW, scaleH, false);
			File _fileImage = File.createTempFile(UUID.randomUUID().toString().replaceAll("/-", ""), ("." + filePrefix));
			ImageIO.write(bufferImage, filePrefix, _fileImage);
			InputStream gridFileStream = new FileInputStream(_fileImage);
			/*
			 * 返回包含所有当前已注册 ImageReader 的 Iterator，这些 ImageReader
			 * 声称能够解码指定格式。 参数：formatName - 包含非正式格式名称 .
			 * （例如 "jpeg" 或 "tiff"）等 。
			 */
			Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(filePrefix);
			ImageReader reader = it.next();
			//获取图片流 
			ImageInputStream iis = ImageIO.createImageInputStream(gridFileStream);
			/*
			 * <p>iis:读取源.true:只向前搜索 </p>.将它标记为 ‘只向前搜索’。
			 * 此设置意味着包含在输入源中的图像将只按顺序读取，可能允许 reader
			 * 避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
			 */
			reader.setInput(iis, true);
			/*
			 * <p>描述如何对流进行解码的类<p>.用于指定如何在输入时从 Java Image I/O
			 * 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件
			 * 将从其 ImageReader 实现的 getDefaultReadParam 方法中返回
			 * ImageReadParam 的实例。
			 */
			ImageReadParam param = reader.getDefaultReadParam();
			/*
			 * 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域，通过 Rectangle 对象
			 * 的左上顶点的坐标（x，y）、宽度和高度可以定义这个区域。
			 */
			Rectangle rect = new Rectangle(pointX, pointY, pointW, pointH);
			//提供一个 BufferedImage，将其用作解码像素数据的目标。 
			param.setSourceRegion(rect);
			/*
			 * 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象，并将
			 * 它作为一个完整的 BufferedImage 返回。
			 */
			BufferedImage bi = reader.read(0, param);
			//保存新图片 
			File _file = File.createTempFile(UUID.randomUUID().toString().replaceAll("/-", ""), ("." + filePrefix));
			ImageIO.write(bi, filePrefix, _file);
			// 保存图片
			GridFSFile returnGFile = fileService.store(new FileInputStream(_file), gfile.getFilename(), gfile.getContentType());
			List<FileResult> list = new ArrayList<FileResult>();
			list.add(new FileResult(returnGFile.getFilename(), returnGFile.getId().toString()));
			return new ResultEntity<List<FileResult>>(ResultCode.success, list);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 将原图片的BufferedImage对象生成缩略图
	 * source：原图片的BufferedImage对象
	 * targetW:缩略图的宽
	 * targetH:缩略图的高
	 */
	public static BufferedImage resize(
			BufferedImage source,
			int targetW,
			int targetH,
			boolean equalProportion) {
		int type = source.getType();
		BufferedImage target = null;
		double sx = (double) targetW / source.getWidth();
		double sy = (double) targetH / source.getHeight();
		//		//这里想实现在targetW，targetH范围内实现等比例的缩放  
		//		//如果不需要等比例的缩放则下面的if else语句注释调即可  
		//		if (equalProportion) {
		//			if (sx > sy) {
		//				sx = sy;
		//				targetW = (int) (sx * source.getWidth());
		//			} else {
		//				sy = sx;
		//				targetH = (int) (sx * source.getHeight());
		//			}
		//		}
		if (type == BufferedImage.TYPE_CUSTOM) {
			ColorModel cm = source.getColorModel();
			WritableRaster raster = cm.createCompatibleWritableRaster(targetW, targetH);
			boolean alphaPremultiplied = cm.isAlphaPremultiplied();
			target = new BufferedImage(cm, raster, alphaPremultiplied, null);
		} else {
			target = new BufferedImage(targetW, targetH, type);
			Graphics2D g = target.createGraphics();
			g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
			g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
			g.dispose();
		}
		return target;
	}

	@RequestMapping(value = "/upload/{type}", method = RequestMethod.POST, produces = "text/html; charset=utf-8")
	public ResultEntity<List<FileResult>> upload(
			@PathVariable("type") String type,
			@RequestParam MultipartFile[] files,
			@RequestParam(required = false) String desc) {
		List<FileResult> list = new ArrayList<FileResult>();
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		// 转型为MultipartHttpRequest：   
		/*
		 * MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		 * // 获得文件：
		 * MultipartFile file21 = multipartRequest.getFile("file");
		 * // 获得文件名：
		 * String filename = file21.getOriginalFilename();
		 */
		log.info("文件大小为：" + request.getContentLength() + "名称：");
		for (MultipartFile file : files) {
			try {
				GridFSFile gfile = fileService.store(file.getInputStream(), file.getOriginalFilename(), file.getContentType(), type, desc);
				//log.info("gfile="+gfile.get);
				list.add(new FileResult(file.getOriginalFilename(), gfile.getId().toString()));
			} catch (IOException e) {
				e.printStackTrace();
				list.add(new FileResult(file.getOriginalFilename(), null, -1));
			}
		}
		return new ResultEntity<List<FileResult>>(ResultCode.success, list);
	}

	@RequestMapping(value = "/uploadPostUrl/{type}", method = RequestMethod.POST)
	public ResultEntity<List<FileResult>> uploadPostUrl(
			@PathVariable("type") String type,
			@RequestParam MultipartFile[] postFiles,
			@RequestParam(required = false) String desc) {
		List<FileResult> list = new ArrayList<FileResult>();
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		// 转型为MultipartHttpRequest：   
		/*
		 * MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		 * // 获得文件：
		 * MultipartFile file21 = multipartRequest.getFile("file");
		 * // 获得文件名：
		 * String filename = file21.getOriginalFilename();
		 */
		for (MultipartFile file : postFiles) {
			try {
				GridFSFile gfile = fileService.store(file.getInputStream(), file.getOriginalFilename(), file.getContentType(), type, desc);
				//log.info("gfile="+gfile.get);
				list.add(new FileResult(file.getOriginalFilename(), gfile.getId().toString()));
			} catch (IOException e) {
				e.printStackTrace();
				list.add(new FileResult(file.getOriginalFilename(), null, -1));
			}
		}
		return new ResultEntity<List<FileResult>>(ResultCode.success, list);
	}

	@RequestMapping(value = "/view/{type}/{name}", method = RequestMethod.GET)
	public void look(
			@PathVariable("type") String type,
			@PathVariable("name") String name,
			HttpServletResponse response) {
		GridFSDBFile gfile = fileService.find(name);
		// 缓存
//		response.setHeader("Pragma", "No-cache");
//		response.setHeader("Cache-Control", "No-cache");
//		response.setDateHeader("Expires", 0);


		Calendar cal = Calendar.getInstance();
		response.setDateHeader("Last-Modified", cal.getTimeInMillis());

		cal.add(Calendar.DATE, 30);
		response.setDateHeader("Expires", cal.getTimeInMillis());

		response.setHeader("Cache-Control", "max-age=2592000");

		try {
			response.setContentType(gfile.getContentType());
			gfile.writeTo(response.getOutputStream());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
